Nutch学习记录:Nutch 插件

#Nutch学习记录:Nutch 插件

Nutch 采用基于插件的体系结构,这也使得 Nutch 具有较好的可扩展性。Nutch 的主要功能基本都是通过插件实现,我们也可以加入新的插件修改和扩展 Nutch 的能力。

1、插件的基础结构

插件类加载器 PluginClassLoader 负责加载插件运行时库和依赖插件的导出库。每 个插件都有自己的类加载器。参数 urls 包括插件自己的导出库、非导出库、属性资 源文件、依赖插件的导出库

1
2
3
4
public class PluginClassLoader extends URLClassLoader {
public PluginClassLoader(URL[] urls, ClassLoader parent) { super(urls, parent);
}
}

扩展点 ExtensionPoint 表示系统可以扩展的功能点。例如,链接过滤是一个可以 扩展的功能点。

Nutch1.10 共提供了 9个扩展点。插件 nutch-extensionpoints 给出这 9 个扩展点的名字(扩展点名字)和全称接口名作为的 ID(扩展点 ID)。其他所有插件都依 赖插件 nutch-extensionpoints,除了给出所有扩展点外(通过 plugin.xml),插 件 nutch-extensionpoints 没有做其他的事情。扩展点在代码一级通过接口定义, 如链接过滤扩展点对应的接口为 org.apache.nutch.net.URLFilter。

扩展点越多,意味着系统扩展和配置的地方越多,系统也越灵活和易进行功能 扩展。

一个 ExtensionPoint 包含多个扩展 Extension。扩展 Extension 表示对扩展点 ExtensionPoint 的具体实现。从设计模式的角度看,ExtensionPoint 相当于发布者 Extension 是监听者。一个发布者可以有多个监听者。

一个插件可以包含多个扩展 Extension,这些扩展 Extension 可以实现不同的扩展点 ExtensionPoint。例如,语言识别插件(language-identifier)包括解析过滤器 和索引过滤器扩展点的实现。每个扩展都有 ID 和扩展实现类(实现扩展点对应 的接口),此外,扩展还可以包含多个特定的属性,例如 Nutch 分析器扩展一般会包括自己处理的语言 lang 这一属性(即声明自己负责什么语言的文本分析)。

类 PluginManifestParser 负责对插件目录列表中的每个插件的描述文件 plugin.xml 进行解析。在每个插件的根目录下都有个 plugin.xml 文件 。 PluginManifestParser 对每个插件的解析的结果保存在 PluginDescriptor 中。

类 PluginDescriptor 表示和 plugin.xml 文件对应的插件信息,包括插件 ID、名字、 版本、提供者、支持的扩展点列表、实现的扩展列表、依赖的插件、字符串资源、导 出库、非导出库和类装载器等。

类 PluginRepository 负责对插件目录中的插件文件进行解析,缓存插件信息,延 迟加载插件,支持对插件各种信息的查询。该类是一个可执行类,可以执行插件 中带有 main 方法的类。

有两个类的作用不太清晰,或者说它们并没有真正使用。其中一个 Plugable,这 是一个标记接口,另一个是 Plugin,表示插件。

2、插件构件


插件构建的基本步骤:

  1. 主 build.xml 是项目根目录下的构建文件,其中的 compile-plugins 目标完成所有
    插件的构建。
  2. 主build.xml中的compile-plugins目标调用src/plugin/build.xml中的deploy目标 。 src/plugin/build.xml 中的 deploy 目标依次调用所有插件目录下的 build.xml 中的 deploy 目标。

    若添加新的插件,需要在 src/plugin/build.xml 中的 deploy 目标中加入如下一行:
    < ant dir=”插件名” target=”deploy”/>
    插件名是一般是插件子目录名。

  3. 插件目录下的 build.xml 利用 src/plugin/build-plugin.xml 完成插件的基本构建。每
    个插件的定制构建可以在插件目录下的 build.xml 中完成。
    构建文件 src/plugin/build-plugin.xml 提供了插件构建的基本框架,它还定义了一
    些可以覆盖的目标,例如插件初始化、插件依赖等。

每个插件的基本构建过程:(位于 src/plugin/build-plugin.xml 中)

  1. (init 目标)创建目录 build/<插件名>、build/<插件名>/classes、build/<插件名 >/test。
  2. (init-plugin 目标)完成插件构建的其他初始化工作,这个目标可以在插件目 录下的 build.xml 中修改覆盖,缺省为空。
  3. (deps-jar 目标)构建插件编译依赖(对该插件依赖的其他插件进行先编译, 产生的 jar 路径放到 plugin.deps 路径属性中),这个目标可以在插件目录下 的 build.xml 中修改覆盖,缺省为空。
  4. (compile 目标)对插件源代码编译。编译使用的类路径包括:build/<插件名 >/classes、build/classes、nutch 根目录 lib 子目录下的 JAR、插件目录 lib 子目录下 的 JAR 包、路径 plugin.deps(插件额外类路径,缺省为空)。路径 plugin.deps 可以在插件目录下的 build.xml 中重定义。
  5. (jar 目标)对 build/<插件名>/classes 中类文件打包,JAR 放在 build/<插件名 >目录下。
  6. (deps-test)单元测试目标。
  7. (deploy 目标)创建目录 build/plugins/<插件名>;将插件描述文件 plugin.xml 拷贝到目录 build/plugins/<插件名>;如果第 5 步生成插件包,将插件包拷贝 到 build/plugins/<插件名>,这步目标为 copy-generated-lib;将插件目录 lib 子 目录下的 JAR 包拷贝到 build/plugins/<插件名>。

下图是nutch-extensionpoints 扩展点插件 build.xml 例子

3、插件异常

  • 一个插件可以依赖其他插件,但是,若产生循环依赖,则插件加载时抛出 CircularDependencyException。
  • 若一个插件依赖的插件不存在或无效,则插件加载时抛出 MissingDependencyException。

4、插件主要配置属性

  • plugin.folders:插件所在的目录列表,缺省位置在 plugins 目录下。该目录可以是 相对目录或绝对目录。若是绝对目录,则直接使用。若是相对目录,则从类路径中 解析。

  • plugin.auto-activation:当被配置为排除(plugin.excludes 中包括,不加载),但是 又被其他插件依赖的时候,是否自动启动,缺省为 true。

  • plugin.includes:要包含的插件名称列表,支持正则表达式方式定义。多个插件间 用|隔开。

  • plugin.excludes:要排除的插件名称列表,支持正则表达式方式定义。

以上这些属性可以在 nutch-site.xml 中重新定义。

5、插件描述文件

插件描述文件 plugin.xml 位于插件根目录下,插件加载时被
PluginManifestParser 解析产生插件、扩展点和扩展等信息。

典型插件文件 plugin.xml 中包括 5 部分信息:

  1. 提供插件发布的扩展点。这部分可选。只有插件 nutch-extensionpoints 使 用。
  2. 提供插件基本信息,包括 ID、名字、版本、提供者、插件类(好像没有使 用),这部分必须。
  3. 提供插件运行时信息,包括插件导出 Jar 包和插件 lib 子目录下的 JAR 包,这部分可选;
  4. 提供插件依赖插件信息,这部分可选;
  5. 可以包括多个插件实现的扩展,每个扩展包括扩展 ID、扩展名字、扩展 实现的扩展点 ID、实现 ID、实现类名和实现相关属性,这部分可选。

插件描述文件如图:

库插件 lib-regex-filter 的插件描述文件如下:

该插件没有扩展和实现,更没有扩展点,它提供基于模式匹配链接过滤插件 (urlfilter-regex 和 urlfilter-automation)的基础实现。

6、扩展点

插件 nutch-extensionpoints 发布 nutch 插件系统支持的扩展点,其他插件不发布 扩展点。因此,nutch-extensionpoints 插件只包括插件基本信息和多个扩展点信息, 扩展点信息包括以类名标识的扩展点 ID 和扩展点名字。
Nutch1.2 有 15 个扩展点。可以对 nutch 支持的扩展点进行修改,添加新的扩展点。
nutch-extensionpoints 的插件文件 plugin.xml(Nutch1.2)如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<plugin
id="nutch-extensionpoints"
name="the nutch core extension points"
version="0.8.0"
provider-name="nutch.org">

<extension-point
id="org.apache.nutch.clustering.OnlineClusterer" 扩展点 ID,类名,一般是接口
name="Nutch Online Search Results Clustering Plugin"/> 扩展点名字

<extension-point
id="org.apache.nutch.indexer.field.FieldFilter"
name="Nutch Field Filter"/>

<extension-point
id="org.apache.nutch.indexer.IndexingFilter"
name="Nutch Indexing Filter"/>

<extension-point
id="org.apache.nutch.ontology.Ontology"
name="Ontology Model Loader"/>

<extension-point
id="org.apache.nutch.parse.Parser"
name="Nutch Content Parser"/>

<extension-point
id="org.apache.nutch.parse.HtmlParseFilter"
name="HTML Parse Filter"/>

<extension-point
id="org.apache.nutch.protocol.Protocol"
name="Nutch Protocol"/>

<extension-point
id="org.apache.nutch.searcher.QueryFilter"
name="Nutch Query Filter"/>

<extension-point
id="org.apache.nutch.net.URLFilter"
name="Nutch URL Filter"/>

<extension-point
id="org.apache.nutch.net.URLNormalizer"
name="Nutch URL Normalizer"/>

<extension-point
id="org.apache.nutch.analysis.NutchAnalyzer"
name="Nutch Analysis"/>

<extension-point
id="org.apache.nutch.searcher.response.ResponseWriter"
name="Nutch Search Results Response Writer"/>

<extension-point
id="org.apache.nutch.searcher.Summarizer"
name="Nutch Summarizer"/>

<extension-point
id="org.apache.nutch.scoring.ScoringFilter"
name="Nutch Scoring"/>

<extension-point
id="org.apache.nutch.segment.SegmentMergeFilter"
name="Nutch Segment Merge Filter"/>
</plugin>

由于查询处理 Nutch1.9 采用 Solr 进行处理,因此 Nutch1.9 只有 9 个扩展点,如下
所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<plugin
id="nutch-extensionpoints"
name="the nutch core extension points"
version="2.0.0"
provider-name="nutch.org">
<!-- this file hosts all extension points nutch core code offers.
Please not that plugins can define extension points as well to be extendable.-->
<extension-point id="org.apache.nutch.indexer.IndexingFilter" name="Nutch Indexing Filter"/>

<extension-point
id="org.apache.nutch.indexer.IndexWriter"
name="Nutch Index Writer"/>

<extension-point
id="org.apache.nutch.parse.Parser"
name="Nutch Content Parser"/>

<extension-point
id="org.apache.nutch.parse.HtmlParseFilter"
name="HTML Parse Filter"/>

<extension-point
id="org.apache.nutch.protocol.Protocol"
name="Nutch Protocol"/>

<extension-point
id="org.apache.nutch.net.URLFilter"
name="Nutch URL Filter"/>

<extension-point
id="org.apache.nutch.net.URLNormalizer"
name="Nutch URL Normalizer"/>

<extension-point
id="org.apache.nutch.scoring.ScoringFilter"
name="Nutch Scoring"/>

<extension-point
id="org.apache.nutch.segment.SegmentMergeFilter"
name="Nutch Segment Merge Filter"/>

</plugin>

Nutch1.9 扩展点和插件列如图:

7、新增扩展点

如果需要对系统中某个功能特性一般化,并需要通过插件的形式进行灵活配
置和扩展,可以将该功能特性抽象为扩展点。
新增扩展点首先是向系统中加入表达功能特性的接口类型定义。
然后,向插件 nutch-extensionpoints 的 plugin.xml 中加入扩展点描述:
< extension-point id=”扩展点接口全称名” name=”扩展点名称”/>

8、新增插件

新增插件(对系统中某种功能需要进行另外一种实现)除了需要实现现有扩
展点接口,还需要建立插件配置和构建环境。主要内容包括:

  1. 在 src/plugin 下建立插件目录结构。假设插件名为 p,则 src/plugin/p/src/java 目录存放插件源代码,src/plugin/p/src/test 存放插件单元测试代码 。 src/plugin/p/build.xml 为插件构建文件,src/plugin/p/plugin.xml 为插件描述文 件,src/plugin/p/ivy.xml 为插件 ivy 依赖文件。
  2. 编码实现特定扩展点接口。
  3. 编写插件描述文件 src/plugin/p/plugin.xml。简单的方法是拷贝现有同扩展点
    插件的描述文件,再进行修改。共有以下几种类型的插件描述文件:
    (1)插件 nutch-extensionpoints 的描述文件只声明扩展点,这种插件描述文 件我们新增插件用不到,要增加扩展点时向 nutch-extensionpoints 插件描述文件中加入即可。
    (2)基础实现插件,如 lib-urlfilter-regex,该类插件作为其他插件实现的基础,插件描述文件中没有 requires 和 extension 部分。插件描述文件如下:
    (3)一般插件。
  4. 建立构建环境。
    (1)首先编写构建文件 src/plugin/p/build.xml,和 plugin.xml 类似,可以对现有类 似文件进行少量修改完成;
    (2)修改 src/plugin/build.xml 文件,在 deploy 目标中加入对 src/plugin/p/build.xml 的调用,一般为< ant dir=”p” target=”deploy”/>;
    (3)添加 ivy.xml 文件,可能需要加入对 jar 包的依赖。
  5. 需要时再 nutch-site.xml 中 plugin.include 属性中激活新增插件。